#!/usr/bin/env python

from errno import *
from glob import *
from os import *
from os.path import *
from pprint import *
from shlex import *
from subprocess import *
from tempfile import *
import tempfile

def check_call(*pargs, **kwargs):
    import subprocess
    #print subprocess.list2cmdline(pargs[0])
    subprocess.check_call(*pargs, **kwargs)

# flags that all C/C++ compilers will use
CCXXFLAGS = [
        #"-Winline",
        "-Wextra",
        "-Wmissing-format-attribute",
        "-Wall",
        "-Wfloat-equal",
        "-fdiagnostics-show-option",
        "-Werror=return-type",
        #"-fno-exceptions",
        "-D_GNU_SOURCE",
        "-D_FILE_OFFSET_BITS=64",
        #"-save-temps",
    ]
CC = split(environ.get("CC", "cc")) + CCXXFLAGS + [
        "-Werror-implicit-function-declaration",
        "-std=gnu99",
        "-x", "c",
        "-Wshadow",
    ]
CXX = split(environ.get("CXX", "c++")) + CCXXFLAGS + [
        "-std=gnu++0x",
        "-Woverloaded-virtual",
        #"-fpermissive",
        "-Wno-invalid-offsetof",
    ]
if environ.get("OS", None) != "Windows_NT":
    FUSE_FLAGS = split(Popen(
            ["pkg-config", "--cflags", "--libs", "fuse"],
            stdout=PIPE).communicate()[0]) + [
            "-DFUSE_USE_VERSION=28",
        ]
FLAGS = split(environ.get("FLAGS", "-ftrapv -g"))

builddir = mkdtemp(prefix="cpfs-")

def thingy(target, sources=None, objects=None, flags=None, linker=None,
        compiler=None):
    print "Building", target
    if objects is None:
        objects = []
    for src in sources or []:
        if not isfile(src):
            for suf in [".c", ".cc", ".cpp", ".C"]:
                if isfile(src + suf):
                    src += suf
                    break
        try:
            makedirs(join(builddir, dirname(src)))
        except OSError as exc:
            if exc.errno != EEXIST:
                raise
        obj = mkstemp(prefix=join(builddir, src)+".o.")[1]
        objects.append(obj)
        print "Compiling", src
        check_call(
                (compiler or (CC if src.endswith(".c") else CXX))
                + ["-c", src, "-o", obj] + (flags or []) + FLAGS)
    print "Linking", target
    check_call(
            (linker or compiler or CXX)
            + ["-o", target] + objects + (flags or []) + FLAGS)
    if "-shared" in flags:
        arname = splitext(target)[0] + ".a"
        print "Archiving", arname
        check_call(["ar", "-cq", arname] + objects)

thingy( "libcpfs.so",
        sources=iglob("libcpfs/*.c*"),
        flags=[
            "-Iinclude",
            "-DCPFS_SIMD_ALIGNED",
            "-DCPFS_USE_BUILTIN",
            "-shared",
            #"-fPIC",
        ],
        #compiler=CC,
    )
thingy( "mount.cpfs",
        ["src/mount.cpfs.c", "src/cpfsfuse.c"],
        flags=FUSE_FLAGS+["-std=gnu99", "-Iinclude", "-L.", "-lcpfs"])
thingy( "mkfs.cpfs",
        ["src/mkfs.cpfs.cpp"],
        flags=["-L.", "-lcpfs", "-lrt", "-lboost_program_options", "-Iinclude"])
thingy( "systest",
        ["src/systest.c"],
        flags=["-Iinclude"])
